using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Practices.CompositeWeb.Interfaces;
using System.IO;
using CompositeWeb.Extensions.Configuration;
using System.Web.Configuration;
using System.Configuration;
using CompositeWeb.Extensions.Interfaces;

namespace CompositeWeb.Extensions.Services
{
    public class WebConfigModuleInfoStore : ICustomModuleInfoStore
    {
        string _baseDirectory;

        /// <summary>
        /// Initializes a new instance of <see cref="WebConfigModuleInfoStore"/>.
        /// </summary>
        public WebConfigModuleInfoStore()
            : this(String.Empty)
        {
        }

        /// <summary>
        /// Initializes a new instance of <see cref="WebConfigModuleInfoStore"/>.
        /// </summary>
        /// <param name="baseDirectory">The directory from which to start searching for the 
        /// configuration files.</param>
        public WebConfigModuleInfoStore(string baseDirectory)
        {
            _baseDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, baseDirectory);
        }

        /// <summary>
        /// Gets the module configuration data.
        /// </summary>
        /// <returns>A <see cref="ModulesConfigurationSection"/> instance.</returns>
        public CustomModulesConfigurationSection GetModuleConfigurationSection()
        {
            CustomModulesConfigurationSection globalSection = new CustomModulesConfigurationSection();
            PopulateSection(globalSection, _baseDirectory);
            return globalSection;
        }

        private void PopulateSection(CustomModulesConfigurationSection section, string rootDirectory)
        {
            foreach (string fileName in Directory.GetFiles(rootDirectory, "Web.Config", SearchOption.TopDirectoryOnly))
            {
                System.Configuration.Configuration configuration = GetConfiguration(Path.Combine(rootDirectory, fileName));
                CustomModulesConfigurationSection localSection = (CustomModulesConfigurationSection)configuration.GetSection("compositeWeb/modules");
                if (localSection != null)
                {
                    foreach (CustomModuleConfigurationElement module in localSection.Modules)
                    {
                        if (!section.Modules.Contains(module.Name))
                        {
                            section.Modules.Add(module);
                        }
                    }
                }
            }
            foreach (string childDirectory in Directory.GetDirectories(rootDirectory))
            {
                PopulateSection(section, childDirectory);
            }
        }

        private static System.Configuration.Configuration GetConfiguration(string configFilePath)
        {
            System.Configuration.Configuration configuration;
            System.Web.HttpContext context = System.Web.HttpContext.Current;
            if (context == null)
            {
                configuration = GetConfigurationForCustomFile(configFilePath);
            }
            else
            {
                configuration = WebConfigurationManager.OpenWebConfiguration(context.Request.ApplicationPath + "/" + configFilePath.Replace(context.Request.PhysicalApplicationPath, ""));
            }
            return configuration;
        }

        private static System.Configuration.Configuration GetConfigurationForCustomFile(string fileName)
        {
            ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
            fileMap.ExeConfigFilename = fileName;
            File.SetAttributes(fileMap.ExeConfigFilename, FileAttributes.Normal);
            return ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
        }
    }
}
